package com.h3c.ptability.service.impl;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.eos.common.util.IdWorker;
import com.h3c.ptability.bo.ElectronicSignBO;
import com.h3c.ptability.cache.UserCache;
import com.h3c.ptability.dto.electronicSign.PtEsignSceneAttrDTO;
import com.h3c.ptability.dto.electronicSign.PtEsignSceneDTO;
import com.h3c.ptability.dto.electronicSign.PtEsignSceneTemplateDTO;
import com.h3c.ptability.entity.PtEsignDocTemplate;
import com.h3c.ptability.entity.PtEsignScene;
import com.h3c.ptability.entity.PtEsignSceneAttr;
import com.h3c.ptability.entity.PtEsignSceneTemplate;
import com.h3c.ptability.mapper.PtEsignSceneMapper;
import com.h3c.ptability.mapstruct.PtEsignSceneAttrMapstruct;
import com.h3c.ptability.mapstruct.PtEsignSceneMapstruct;
import com.h3c.ptability.mapstruct.PtEsignSceneTemplateMapstruct;
import com.h3c.ptability.service.IPtEsignDocTemplateService;
import com.h3c.ptability.service.IPtEsignSceneAttrService;
import com.h3c.ptability.service.IPtEsignSceneService;
import com.h3c.ptability.service.IPtEsignSceneTemplateService;
import com.h3c.ptability.utils.AppBusinessException;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 电子签实际场景定义实现类
 *
 * @author chenyifan
 * @since 2022-05-19 10:59:58
 */
@Service
@AllArgsConstructor
public class PtEsignSceneServiceImpl extends ServiceImpl<PtEsignSceneMapper, PtEsignScene> implements IPtEsignSceneService {

    private final PtEsignSceneMapper ptEsignSceneMapper;
    private final IPtEsignSceneTemplateService iPtEsignSceneTemplateService;
    private final IPtEsignDocTemplateService iPtEsignDocTemplateService;
    private final IPtEsignSceneAttrService iPtEsignSceneAttrService;

    @Override
    public List<PtEsignScene> getSceneByTypeAndAppId(Integer sceneType, String appId) {
        return list(new QueryWrapper<PtEsignScene>().lambda()
                .eq(PtEsignScene::getSceneType, sceneType)
                .eq(PtEsignScene::getAppId, appId)
                .orderByAsc(PtEsignScene::getSceneOrder)
        );
    }

    @Override
    public IPage<PtEsignSceneDTO> pageEsignScene(IPage<PtEsignScene> page, PtEsignSceneDTO scene) {

        //查询Scene记录
        LambdaQueryWrapper<PtEsignScene> queryWrapper = new QueryWrapper<PtEsignScene>().lambda();
        if (scene.getSceneType() != null) {
            queryWrapper.eq(PtEsignScene::getSceneType, scene.getSceneType());
        }
        if (StringUtils.isNotBlank(scene.getSceneName())) {
            queryWrapper.like(PtEsignScene::getSceneName, scene.getSceneName());
        }
        if (StringUtils.isNotBlank(scene.getAppId())) {
            queryWrapper.eq(PtEsignScene::getAppId, scene.getAppId());
        }
        IPage<PtEsignScene> scenePage = ptEsignSceneMapper.selectPage(page, queryWrapper);
        List<PtEsignScene> records = scenePage.getRecords();
        if (records.isEmpty()) {
            return new Page<>();
        }

        //查询doc
        List<PtEsignSceneTemplate> templateList = iPtEsignSceneTemplateService.selectEsignSceneTemplateByScene(records);
        List<PtEsignDocTemplate> docList = iPtEsignDocTemplateService.getTemplateListByTemplateList(templateList);

        //doc转变成k-v
        Map<String, String> docMap = docList.stream()
                .collect(Collectors.toMap(PtEsignDocTemplate::getTemplateId, PtEsignDocTemplate::getDocName));
        Map<String, String> docNameStrList = templateList.stream().collect(
                Collectors.groupingBy(PtEsignSceneTemplate::getSceneId,
                        Collectors.collectingAndThen(Collectors.toList(),
                                o -> o.stream().map(t -> docMap.get(t.getTemplateId()))
                                        .collect(Collectors.joining(",")))));
        //修改返回值
        IPage<PtEsignSceneDTO> convert = scenePage.convert(s -> {
            PtEsignSceneDTO sceneDTO = PtEsignSceneMapstruct.INSTANCE.entityToDto(s);
            String nameStr = docNameStrList.get(s.getSceneId());
            sceneDTO.setTemplateName(nameStr);
            return sceneDTO;
        });
        convert.setTotal(scenePage.getTotal());
        return convert;
    }

    @Override
    public PtEsignSceneDTO selectSignById(PtEsignSceneDTO dto) {
        String sceneId = dto.getSceneId();
        PtEsignScene ptEsignScene = getById(sceneId);
        if (ptEsignScene == null) {
            throw new AppBusinessException("场景不存在");
        }

        PtEsignSceneDTO sceneDTO = PtEsignSceneMapstruct.INSTANCE.entityToDto(ptEsignScene);

        List<PtEsignSceneTemplateDTO> docList = iPtEsignSceneTemplateService.getTemplateListBySceneId(sceneId);
        sceneDTO.setDocList(docList);

        List<PtEsignSceneAttr> ptEsignSceneAttrList = iPtEsignSceneAttrService.getAttrBySceneId(sceneId);
        List<PtEsignSceneAttrDTO> attrDtoList = PtEsignSceneAttrMapstruct.INSTANCE.entityToDto(ptEsignSceneAttrList);

        sceneDTO.setAttrList(attrDtoList);
        return sceneDTO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateByEsignScene(PtEsignSceneDTO dto) {
        String sceneId;

        if (StringUtils.isNotBlank(dto.getSceneId())) {
            sceneId = dto.getSceneId();
            iPtEsignSceneAttrService.deleteSceneAttrBySceneId(sceneId);
            iPtEsignSceneTemplateService.deleteSceneTemplateBySceneId(sceneId);
        } else {
            sceneId = IdWorker.nextId() + "";
            dto.setSceneId(sceneId);
        }

        List<PtEsignSceneAttrDTO> dtoAttrList = dto.getAttrList();
        List<PtEsignSceneAttr> attrs = dtoAttrList.stream()
                .map(PtEsignSceneAttrMapstruct.INSTANCE::dtoToEntity)
                .peek(attr -> {
                    if (StringUtils.isBlank(attr.getAttrId())) {
                        attr.setAttrId(IdWorker.nextId() + "");
                    }
                    attr.setSceneId(sceneId);
                })
                .collect(Collectors.toList());
        iPtEsignSceneAttrService.saveBatch(attrs);

        List<PtEsignSceneTemplateDTO> docList = dto.getDocList();
        List<PtEsignSceneTemplate> templateList = docList.stream()
                .map(PtEsignSceneTemplateMapstruct.INSTANCE::dtoToEntity)
                .peek(template -> template.setSceneId(sceneId))
                .collect(Collectors.toList());
        iPtEsignSceneTemplateService.saveBatch(templateList);

        PtEsignScene esignScene = PtEsignSceneMapstruct.INSTANCE.dtoToEntity(dto);
        esignScene.setOperateTime(new Date());
        esignScene.setOperatorInfo(UserCache.getLoginUserNameAndId());
        return saveOrUpdate(esignScene);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteEsignScene(PtEsignSceneDTO dto) {
        String sceneId = dto.getSceneId();

        iPtEsignSceneAttrService.deleteSceneAttrBySceneId(sceneId);
        iPtEsignSceneTemplateService.deleteSceneTemplateBySceneId(sceneId);

        return removeById(sceneId);
    }

    @Override
    public HashMap<String, List<PtEsignSceneTemplateDTO>> matchSceneFiles(ElectronicSignBO electronicSignBO) {
        List<JSONObject> userInfoList = JSONUtil.toList(electronicSignBO.getUserData().getJSONArray(ElectronicSignBO.USER_INFO_LIST), JSONObject.class);
        List<PtEsignScene> esignScenes = getSceneByTypeAndAppId(electronicSignBO.getSceneType(), electronicSignBO.getAppId());
        HashMap<String, List<PtEsignSceneTemplateDTO>> result = new HashMap<>(userInfoList.size());
        for (JSONObject userInfo : userInfoList) {
            PtEsignScene suitScene = null;
            for (PtEsignScene esignScene : esignScenes) {
                if (iPtEsignSceneAttrService.judgeSuitScene(userInfo, esignScene)) {
                    suitScene = esignScene;
                    break;
                }
            }
            if (Objects.isNull(suitScene)) {
                result.put(userInfo.getStr(ElectronicSignBO.WORKER_ID), new ArrayList<>());
            } else {
                result.put(userInfo.getStr(ElectronicSignBO.WORKER_ID),
                        iPtEsignSceneTemplateService.getTemplateListBySceneId(suitScene.getSceneId()));
            }
        }

        return result;
    }

    @Override
    public List<PtEsignScene> getEsignSceneList(String appId, Integer sceneType) {
        return list(new QueryWrapper<PtEsignScene>().lambda()
                .eq(PtEsignScene::getAppId, appId)
                .eq(Objects.nonNull(sceneType), PtEsignScene::getSceneType, sceneType)
        );
    }

}

